#pragma once
#include "../Common/file_utility.hpp"
#include <glad/glad.h>

class Shader
{
public:
    Shader(const std::string &vertexShaderPath, const std::string& fragmentShaderPath) {
        this->vertexShader = CompileShader(vertexShaderPath, GL_VERTEX_SHADER);
        this->fragShader = CompileShader(fragmentShaderPath, GL_FRAGMENT_SHADER);
        this->program = glCreateProgram();
        glAttachShader(this->program, this->vertexShader);
        glAttachShader(this->program, this->fragShader);
        glLinkProgram(this->program);

        int32_t success;
        glGetProgramiv(this->program, GL_LINK_STATUS, &success);
        if(success == GL_FALSE) {
            char infoLog[512];
            glGetProgramInfoLog(this->program, 512, nullptr, infoLog);
            std::cout << "ERROR:SHADER::PROGRAM::LINKING_FAILED: " << infoLog << std::endl;
            return;
        }

        glDeleteShader(this->vertexShader);
        glDeleteShader(this->fragShader);
    }

    void Use() {
        glUseProgram(this->program);
    }

    void Dispose() {
        if(!isDispose) {
            glDeleteProgram(this->program);
            isDispose = true;
        }
    }

private:
    uint32_t vertexShader = 0;
    uint32_t fragShader = 0;
    uint32_t program = 0;

    bool isDispose = false;

    static uint32_t CompileShader(const std::string& path, int32_t shaderType) {
        const uint32_t shader = glCreateShader(shaderType);
        const std::string shaderSource = read_file(path);
        const char * shaderSourcePtr = shaderSource.c_str();
        glShaderSource(shader, 1, &shaderSourcePtr, nullptr);
        glCompileShader(shader);
        int32_t success;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if(success == GL_FALSE) {
            char infoLog[512];
            glGetShaderInfoLog(shader, 512, nullptr, infoLog);
            std::cerr << "ERROR:SHADER" << path << infoLog << std::endl;
            return 0;
        }
        return shader;
    }

    ~Shader() {
        if(isDispose == false) {
            std::cout << "Waring Shader GPU Resources not been released" << std::endl;
        }
    }
};